import copy
import pygame
import random
from map_config import *
from button_event import *
import sound

ai_delay_time = 500

sound_flag = 0
#是否决定播放成功或者失败的音乐的标志位

#游戏得分
game_point = 0
game_step = 0
isAdd = 0

#板的二维数组
board = [
        [0,2,4,8],
        [0,16,32,64],
        [128,0,256,0],
        [512,1024,0,2048]
        ]
#返还row行  col列
#board[a,b] 对应的是a行b列
#比如说 
#board = [[0,2,4,8],
#         [0,16,32,64],
#         [128,0,256,0],
#         [512,1024,0,2048]]
#         board[0][1] = 2

#板的栈 用于记录过去的值
board_stack = []
#得分的栈 用于记录过去的得分
point_stack = []
#步数的栈 用于记录过去的行动 0空 1上 2下 3左 4右
step_stack = []
#(之前弄过一个MyStack 因为有BUG只能放弃了)

#获取得分
def get_point():
    return game_point
#获取步数
def get_step():
    return game_step


#获取任意行列的方块的值
def get_block_num(row,col):
    return board[row][col]

#清除地图
def clear_map():
    for row in range(0,4):
        for col in range(0,4):
            board[row][col] = 0

#判断里面有没有空的格子
def isEmpty():
    for row in range(0,4):
        for col in range(0,4):
            if(board[row][col] == 0):
                return True
    return False

#给数组添加新的块
#有四分之一的可能产生4
#四分之三的可能产生2
def create_new_block():
    rows = random.randint(0,3)
    cols = random.randint(0,3)#生成行和列

    while(board[rows][cols]!=0):
        rows = random.randint(0,3)
        cols = random.randint(0,3)#如果这个位置不是空的，就继续生成行和列
    #print(rows,cols,board[rows][cols])
    value = random.randint(0,3)
    if(value == 3):
        board[rows][cols] = 4
    else:
        board[rows][cols] = 2

#向上移动
def move_up():
    global game_point
    global game_step
    global isAdd
    isAdd = 0
    for col in range(0,4):
        index = 0
        for row in range(1,4):
            if board[row][col] > 0:
                #当前数字等于上边数字
                #上边数字 = 上边数字 + 当前数字, 当前数字 = 0
                if board[row][col] == board[index][col]:
                    board[index][col] = board[row][col] + board[index][col]
                    game_point += board[row][col]
                    board[row][col] = 0
                    isAdd = 1
                    index += 1
                #当前数字不等于上边数字
                elif board[index][col] == 0:#当前数字上边有0
                    #上边数字 = 当前数字, 当前数字 = 0
                    board[index][col] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
                else:
                    index += 1
                #去除漏网之鱼
                #index相当于慢指针，j相当于快指针
                #也就是说快指针和慢指针中间可能存在一个以上的空格，或者index和j并未相邻
                #上边数字 = 0
                #数值: 上边数字 = 当前数字, 当前数字 = 0
                if board[index][col] == 0:
                    board[index][col] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
    game_step += isAdd
    return isAdd

#向下移动
def move_down():
    global game_point
    global game_step
    global isAdd
    isAdd = 0
    for col in range(0,4):
        index = 3
        for row in range(2,-1,-1):
            if board[row][col] > 0:
                #当前数字等于下边数字
                #下边数字 = 下边数字 + 当前数字, 当前数字 = 0
                if board[row][col] == board[index][col]:
                    board[index][col] = board[row][col] + board[index][col]
                    game_point += board[row][col]
                    board[row][col] = 0
                    index -= 1
                    isAdd = 1
                #当前数字不等于下边数字
                elif board[index][col] == 0:#当前数字上边有0
                    #下边数字 = 当前数字, 当前数字 = 0
                    board[index][col] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
                else:
                    index -= 1
                #去除漏网之鱼
                #index相当于慢指针，j相当于快指针
                #也就是说快指针和慢指针中间可能存在一个以上的空格，或者index和j并未相邻
                #下边数字 = 0
                #数值: 下边数字 = 当前数字, 当前数字 = 0
                if board[index][col] == 0:
                    board[index][col] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
    game_step += isAdd
    return isAdd

#向左移动
def move_left():
    global game_point
    global game_step
    global isAdd
    isAdd = 0
    for row in range(0,4):
        index = 0
        for col in range(1,4):
            if board[row][col] > 0:
                #当前数字等于下边数字
                #下边数字 = 下边数字 + 当前数字, 当前数字 = 0
                if board[row][col] == board[row][index]:
                    board[row][index] = board[row][col] + board[row][index]
                    game_point += board[row][col]
                    board[row][col] = 0
                    index += 1
                    isAdd = 1
                #当前数字不等于下边数字
                elif board[row][index] == 0:#当前数字上边有0
                    #下边数字 = 当前数字, 当前数字 = 0
                    board[row][index] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
                else:
                    index += 1
                #去除漏网之鱼
                #index相当于慢指针，j相当于快指针
                #也就是说快指针和慢指针中间可能存在一个以上的空格，或者index和j并未相邻
                #下边数字 = 0
                #数值: 下边数字 = 当前数字, 当前数字 = 0
                if board[row][index] == 0:
                    board[row][index] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
    game_step += isAdd
    return isAdd

#向右移动
def move_right():
    global game_point
    global game_step
    global isAdd
    isAdd = 0
    for row in range(0,4):
        index = 3
        for col in range(2,-1,-1):
            if board[row][col] > 0:
                #当前数字等于下边数字
                #下边数字 = 下边数字 + 当前数字, 当前数字 = 0
                if board[row][col] == board[row][index]:
                    board[row][index] = board[row][col] + board[row][index]
                    game_point += board[row][col]
                    board[row][col] = 0
                    index -= 1
                    isAdd = 1
                #当前数字不等于下边数字
                elif board[row][index] == 0:#当前数字上边有0
                    #下边数字 = 当前数字, 当前数字 = 0
                    board[row][index] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
                else:
                    index -= 1
                #去除漏网之鱼
                #index相当于慢指针，j相当于快指针
                #也就是说快指针和慢指针中间可能存在一个以上的空格，或者index和j并未相邻
                #下边数字 = 0
                #数值: 下边数字 = 当前数字, 当前数字 = 0
                if board[row][index] == 0:
                    board[row][index] = board[row][col]
                    board[row][col] = 0
                    isAdd = 1
    game_step += isAdd
    return isAdd

#向上移动完全操作
def go_move_up():
    global board_stack
    global point_stack
    global step_stack

    global board

    board2 = copy.deepcopy(board)

    if move_up() == 1: #往上移 只有当移动成功了 才创建新的方块 并且把当前的情况入栈
        create_new_block()
        #入栈
        board_stack.append(board2)
        point_stack.append(get_point())
        step_stack.append(1)
        #产生声音
        sound.slide_sound()

#向下移动完全操作
def go_move_down():
    global board_stack
    global point_stack
    global step_stack

    global board

    board2 = copy.deepcopy(board)

    if move_down() == 1: #往下移 只有当移动成功了 才创建新的方块 并且把当前的情况入栈
        create_new_block()
        #入栈
        board_stack.append(board2)
        point_stack.append(get_point())
        step_stack.append(2)
        #产生声音
        sound.slide_sound()
        
#向左移动完全操作
def go_move_left():
    global board_stack
    global point_stack
    global step_stack

    global board

    board2 = copy.deepcopy(board)

    if move_left() == 1: #往左移 只有当移动成功了 才创建新的方块 并且把当前的情况入栈
        create_new_block()
        #入栈
        board_stack.append(board2)
        point_stack.append(get_point())
        step_stack.append(3)
        #产生声音
        sound.slide_sound()
        
#向右移动完全操作
def go_move_right():
    global board_stack
    global point_stack
    global step_stack

    global board

    board2 = copy.deepcopy(board)

    if move_right() == 1: #往右移 只有当移动成功了 才创建新的方块 并且把当前的情况入栈
        create_new_block()
        #入栈
        board_stack.append(board2)
        point_stack.append(get_point())
        step_stack.append(4)
        #产生声音
        sound.slide_sound()

#开始基础游戏（后面可能还会添加别的功能）
def start_base_game():
    #定义全局变量
    global game_step
    global game_point
    global isAdd

    global board_stack
    global point_stack
    global step_stack

    global board

    board2 = copy.deepcopy(board)
    #清空地图 + 创建两个格子
    clear_map()
    create_new_block()
    create_new_block()
    #初始化变量
    game_step = 0
    game_point = 0
    isAdd = 0

    ##清空所有的栈
    board_stack = []
    point_stack = []
    step_stack = []
    ##往栈中添加当前的元素
    board_stack.append(board2)
    point_stack.append(get_point())
    step_stack.append(0)
    #声音的处理
    sound.stop_sound()
    sound.background_sound()


ball_x = 0
ball_y = 0
move_enable = 0
#基础游戏进行时
def base_game_going():
    global ball_x,ball_y,move_enable
    global ai_delay_time
    global sound_flag
#游戏正常
    if judge_gameover() == False and judge_gamewin() == False:
        sound_flag = 0
        for event in pygame.event.get():
            #按钮事件检测
            buttonBase.check_event(event)
            buttonReturn.check_event(event)
            buttonAI.check_event(event)
            buttonTips.check_event(event)
            buttonReshow.check_event(event)

            #键盘事件 基本键盘操作
            if event.type == pygame.KEYDOWN:
                if(event.key == pygame.K_LEFT or event.key == pygame.K_a):
                    go_move_left()

                if(event.key == pygame.K_RIGHT or event.key == pygame.K_d):
                    go_move_right()

                if(event.key == pygame.K_UP or event.key == pygame.K_w):
                    go_move_up()

                if(event.key == pygame.K_DOWN or event.key == pygame.K_s):
                    go_move_down()

                if(event.key == pygame.K_z):#Z键加快速度
                    if ai_delay_time > 50:
                        ai_delay_time = ai_delay_time - 50
                if(event.key == pygame.K_x):#X键减慢速度
                    if ai_delay_time < 1000:
                        ai_delay_time = ai_delay_time + 50
            #鼠标事件 滑动鼠标手势
            elif event.type == pygame.MOUSEBUTTONDOWN:
                ball_x,ball_y = pygame.mouse.get_pos()
                if ball_x > start_x and ball_x < start_x + box_size*4:  #限制鼠标手势范围
                    if ball_y > top_of_screen and ball_y < top_of_screen + box_size*4:
                        move_enable = 1
                #print(ball_x,ball_y)

            elif event.type == pygame.MOUSEBUTTONUP:
                if move_enable == 1:
                    move_enable = 0
                    ball_x_2, ball_y_2 =pygame.mouse.get_pos()
                    dX = ball_x_2 - ball_x
                    dY = ball_y_2 - ball_y

                    if abs(dX) > abs(dY):
                        if dX < 0:
                            go_move_left()
                        else:
                            go_move_right()

                    elif abs(dX) < abs(dY):
                        if dY < 0:
                            go_move_up()
                        elif dY > 0:
                            go_move_down()

#游戏失败
    elif judge_gameover() == True:
        if sound_flag == 0:
            sound_flag = 1
            sound.stop_sound()
            sound.fail_sound()
        for event in pygame.event.get():
            #按钮事件检测
            buttonBase.check_event(event)
            buttonReturn.check_event(event)
            buttonAI.check_event(event)
            buttonTips.check_event(event)
            buttonReshow.check_event(event)

#游戏成功
    elif judge_gamewin() == True:
        if sound_flag == 0:
            sound_flag = 1
            sound.stop_sound()
            sound.win_sound()
        for event in pygame.event.get():
            #按钮事件检测
            buttonBase.check_event(event)
            buttonReturn.check_event(event)
            buttonAI.check_event(event)
            buttonTips.check_event(event)
            buttonReshow.check_event(event)

#获取空白方格
def get_empty():
    lst = []
    for row in range(4):
        for col in range(4):
            if board[row][col] == 0:
                lst.append([row, col])
    return lst

#判断游戏是否结束
def judge_gameover():
    #当空白空格不为空时，即游戏未结束
    if isEmpty() == True:
        return False
    #当空白方格为空时，判断是否存在可合并的方格
    for row in range(4):
        for col in range(3):
            if board[row][col] == board[row][col + 1]:
                return False

    for row in range(3):
        for col in range(4):
            if board[row][col] == board[row + 1][col]:
                return False 
    #若不满足以上两种情况，则游戏结束
    return True

#判断游戏是否成功
def judge_gamewin():
#检查是否有2048
    maxnum = 0
    for row in range(0,4):
        for col in range(0,4):
            if(board[row][col] > maxnum):
                maxnum = board[row][col]

    if maxnum == 2048:
        return True
    return False

#撤回功能回调函数（用于给按键事件使用）
def return_callback():
    #定义全局变量
    global game_step
    global game_point
    global isAdd

    global board_stack
    global point_stack
    global step_stack

    global board
    sound.stop_sound()
    sound.background_sound()
    if game_step != 0:
        board = board_stack[-1]
        del board_stack[-1]
    
        game_point = point_stack[-1]
        del point_stack[-1]
    
        del step_stack[-1]
        
        game_step -= 1
    sound.return_sound()











